home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SVM Mac CD-ROM 17
/
SVM Mac CD-ROM - No 17.iso
/
Accès direct
/
Trésors du domaine public
/
Programmation
/
launch-creator
/
notify.cc
< prev
next >
Wrap
Text File
|
1995-06-05
|
6KB
|
192 lines
/*
***********************************************************************
*
* The set of functions below let a (backgound) application post
* synchronous or asynchronous notification messages to the user.
* Synchronous posting means that the posting function does not return until
* the notification message is displayed and the user dismisses it.
* In asynchronous mode, the posting function returns as soon as the
* message is queued into the notification queue (but not yet displayed!).
* The functions use the Notification Manager and the EventManager (via
* function sleep() defined elsewhere to relinquish the CPU control while
* sleeping).
*
* Synchronization between the Notification Manager and the present functions
* A field nmRefCon of the Notification Queue element is used for the
* synchronization: it is reset to 0 when the element is queued and set to
* 1 by a completion routine when the message has been posted.
*
***********************************************************************
*/
/* MacHeaders Included */
#include "mymenv.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <Notification.h>
// Completion routine
static pascal On_completion(NMRecPtr el)
{
NMRemove(el); // Remove the notification request from
// the manager's queue
el->nmRefCon = 1; // Mark the notification element as posted
return 0;
}
// Create a new notification element
static NMRecPtr new_element(const char * mesg)
{
// Allocate space for the element and the string
NMRecPtr el = (NMRecPtr)NewPtr(sizeof(NMRec) + sizeof(Str255));
el->qLink = 0;
el->qType = nmType;
el->nmMark = 0;
el->nmIcon = nil;
el->nmSound = nil; // String is allocated right after the
el->nmStr = (unsigned char *)((char *)el + sizeof(NMRec)); // element
el->nmResp = NewNMProc(On_completion);
el->nmRefCon = 0;
xstrncpy((char *)(el->nmStr),mesg,254);
CtoPstr((char *)el->nmStr);
return el;
}
// Wait until the given element is marked as
// completed (nmRefCon changes its value from 0
// to 1).
// The waiting though busy is gracious enough to let
// other processes running.
static void wait_for_completion(NMRecPtr el)
{
assert( el != 0 );
while( el->nmRefCon == 0 )
sleep(10);
assert( el->nmRefCon == 1 );
}
// Simply check if a request is posted
static Boolean check_if_posted(const NMRecPtr el)
{
return el->nmRefCon == 0 ? FALSE : TRUE;
}
// Dispose of the element
static void dispose_element(NMRecPtr el)
{
assert( el != 0 );
DisposePtr((char *)el);
}
/*
*----------------------------------------------------------------------------
* Managing the queue of pending notification requests
* Note the queue is just a circular list
*/
#define Queue_size 5
static NMRecPtr Queue[Queue_size];
static unsigned int Queue_free_slot_no = 0;
static unsigned int Queue_no_filled_slots = 0;
// Enqueue the element. return FALSE if the queue
// is filled up
static Boolean enqueue(const NMRecPtr el)
{
if( Queue_no_filled_slots >= Queue_size )
return FALSE; // The queue is filled up
Queue[Queue_free_slot_no] = el;
Queue_no_filled_slots++;
if( ++Queue_free_slot_no >= Queue_size ) // Adjust the pointer in a circular way
Queue_free_slot_no = 0;
return TRUE;
}
// Return the head elememt of the queue, or 0 if the
// queue is empty
static NMRecPtr get_head(void)
{
register int index;
if( Queue_no_filled_slots == 0 )
return (NMRecPtr)0;
assert( Queue_free_slot_no < Queue_size );
index = Queue_free_slot_no - Queue_no_filled_slots;
if( index < 0 )
index += Queue_size;
return Queue[index];
}
// Remove the head of the queue
static void remove_head(void)
{
register NMRecPtr el;
assert( Queue_no_filled_slots > 0 && Queue_no_filled_slots <= Queue_size );
el = get_head();
dispose_element(el);
Queue_no_filled_slots--;
}
// Check out if some request in the queue of pending
// request have been posted. If so, remove them
// from the queue.
// Note that we expect requests are posted in the
// order they enqueued, i.e. in the FIFO order
static void check_queue(void)
{
register NMRecPtr el;
while( (el=get_head()) != (NMRecPtr)0 && check_if_posted(el) )
remove_head();
}
/*
*----------------------------------------------------------------------------
* Routing modules
*/
void notify_and_wait(const char * messg,...)
{
va_list args;
char buffer[300];
register NMRecPtr el;
va_start(args,messg); // Init 'args' to the beginning of
// the variable length list of args
assert(strlen(messg) < sizeof(buffer)-100);
vsprintf(buffer,messg,args);
check_queue();
el = new_element(buffer);
assert( NMInstall(el) == noErr );
wait_for_completion(el);
dispose_element(el);
}
// Asynchronous notification
void notify(const char * messg,...)
{
va_list args;
char buffer[300];
register NMRecPtr el;
va_start(args,messg); // Init 'args' to the beginning of
// the variable length list of args
assert(strlen(messg) < sizeof(buffer)-100);
vsprintf(buffer,messg,args);
check_queue();
el = new_element(buffer);
assert( NMInstall(el) == noErr );
while( !enqueue(el) ) // If there are too many outstanding
{ // elements, wait until some are posted
wait_for_completion(get_head());
check_queue();
}
}